﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using Contracts;
using Events;
using Model;
using Tools;

namespace ViewModel
{
    public class DiscussionContainerViewModel : ApplicationViewModel
    {
        #region singleton implementation
        private static DiscussionContainerViewModel _instance;
        static readonly object instanceLock = new object();
     
        public static DiscussionContainerViewModel getInstance() 
        {
            lock (instanceLock)
            {
	            if (_instance == null)
	            {
                    _instance = new DiscussionContainerViewModel();
	            }
	            return _instance;
            }
        }

        #endregion

        #region Commands
        public ICommand CloseDiscussionCommand;
        public ICommand SendMessageCommand;
        #endregion

        #region Events and events handlers
        public delegate void MessageReceivedHandler(object sender, UserMessageEventArgs e);
        public static event MessageReceivedHandler OnMessageReceived;
        #endregion

        #region Accessors / Properties
        ObservableCollection<DiscussionViewModel> discussions;

        private String inputText;
        public String InputText
        {
            get{ return inputText;} 
            set
            { 
                inputText = value;
                OnPropertyChanged("InputText");
            }
        }

        public ObservableCollection<DiscussionViewModel> Discussions
        {
            get
            {
                if (discussions == null)
                {
                    discussions = new ObservableCollection<DiscussionViewModel>();
                    discussions.CollectionChanged += this.OnDiscussionChanged;
                }
                return discussions;
            }
        }
        #endregion

        DiscussionContainerViewModel()
        {
            this.DisplayName = "Discussion Container";
            this.discussions = new ObservableCollection<DiscussionViewModel>();

            //commands
            this.CloseDiscussionCommand = new DelegateCommand(p => CloseDiscussion(p as Contact));
            this.SendMessageCommand = new DelegateCommand(p => SendMessage(p as Contact));
        }

        private void SendMessage(Contact contact)
        {
            this.getModel.SendMessage(contact.Mail, this.InputText);
            this.InputText = "";
        }

        private void CloseDiscussion(Contact contact)
        {
            var discussion = (from d in discussions
                              where d.CurrentContact.Equals(contact)
                              select d).FirstOrDefault();
            discussions.Remove(discussion);
        }


        public void AddDiscussion(Contact contact)
        {
            DiscussionViewModel discussion = (from d in discussions
                              where d.CurrentContact.Mail.Equals(contact.Mail)
                              select d).FirstOrDefault();
            if (discussion == null)
            {
                discussions.Add(new DiscussionViewModel(contact));
            }
            // create event
            
        }

        internal void DisplayMessage(Message message)
        {
            DiscussionViewModel discussion = this.getDiscussion(message.From);
            discussion.AddMessage(message);
        }

        private DiscussionViewModel getDiscussion(Contact with)
        {
            DiscussionViewModel discussion = (from d in discussions
                              where d.CurrentContact.Mail.Equals(with.Mail)
                              select d).FirstOrDefault();
            
            if (discussion == null)
            {
                discussion = new DiscussionViewModel(with);
                Application app = System.Windows.Application.Current;
                if (app != null)
                    app.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(AsyncAdd), discussion);
            }
            return discussion;
        }

        private object AsyncAdd(object discussion)
        {
            this.discussions.Add(discussion as DiscussionViewModel);
            return null;
        }

        void OnDiscussionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (DiscussionViewModel discussion in e.NewItems)
                    discussion.OnRequestClose += this.OnDiscussionRequestClose;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (DiscussionViewModel discussion in e.OldItems)
                    discussion.OnRequestClose -= this.OnDiscussionRequestClose;
        }

        void OnDiscussionRequestClose(object sender, EventArgs e)
        {
            this.Discussions.Remove(sender as DiscussionViewModel);
        }
    }
}
